﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using dal.cgm_production_dao;
using Newtonsoft.Json;
using utils;

namespace bluetooth_test_localfile
{
    public partial class First : Form
    {
        #region
        private SerialPort serialPort1;
        private byte sequenceID = 0x00; // 顺序ID初始值

        // 头指令
        private const byte HeaderCommandDown = 0xA0; // 下位机向上位机发送的头指令
        private const byte HeaderCommandUp = 0xB0;   // 上位机向下位机发送的头指令
        // 数据包长度
        //private const byte DataLength = 0x00;   //数据包长度

        // 状态ID
        private const byte StatusIDReply = 0x00; // 表示需回复数据包，接收方在接收到指令数据后应回复发送方接收响应(ACK)
        private const byte StatusIDConfirm = 0xA0; // 表示确认数据包，为接收方回复发送方的接收响应

        // 产品类型
        private const byte ProductType = 0xBF;

        // 指令类型
        private const byte CommandStartBluetoothTest = 0xE0;    // 开始蓝牙测试
        private const byte CommandSetCode = 0xE1;               // 设置CODE
        private const byte CommandStopBluetoothTest = 0xE2;      // 结束蓝牙测试
        private const byte CommandBluetoothTestResultUpload = 0xD0; // 蓝牙测试结果上传
        private const byte CommandCodeResultUpload = 0xD1; // CODE结果上传
        // 整包校验初始值
        //private const byte InitialChecksum = 0x00;
        // 最大重发次数
        //private const int MaxRetryCount = 3;

        private CancellationTokenSource cts;
        private CancellationTokenSource cts1;
        private Task timeoutTask;

        private const int TimeoutDuration = 60000;

        private bool startTestStatus = false;
        private bool startTestRes = false;
        private bool setCodeStatus = false;
        private bool setCodeRes = false;

        private string stemp = "";

        private string macDown { get; set; }
        //private string hardwareDown { get; set; }
        private string firmwareDown { get; set; }

        private string codeUp { get; set; }
        private string batchUp { get; set; }
        private string firmwareUp { get; set; }



        private const int PBM_SETSTATE = 0x0410;
        private const int PBST_NORMAL = 0x0001;
        private const int PBST_ERROR = 0x0002;
        //private const int PBST_PAUSED = 0x0003;

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l);

        private System.Windows.Forms.Timer deviceCheckTimer;
        private string[] lastKnownPorts;

        #endregion

        private NotifyIcon notifyIcon;

        public First()
        {
            InitializeComponent();
            InitializeDeviceCheck();
            InitializeNotifyIcon();

            if (serialPort1 == null)
            {
                serialPort1 = new SerialPort();
            }
            versionLabel.Text = "v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();

        }

        private void InitializeNotifyIcon()
        {
            notifyIcon = new NotifyIcon();
            notifyIcon.Icon = SystemIcons.Information; // 设置图标
            notifyIcon.Visible = true;
        }

        private void InitializeDeviceCheck()
        {
            deviceCheckTimer = new System.Windows.Forms.Timer();
            deviceCheckTimer.Interval = 1000; // 每5秒检查一次
            deviceCheckTimer.Tick += DeviceCheckTimer_Tick;
            deviceCheckTimer.Start();

            lastKnownPorts = SerialPort.GetPortNames();
        }

        private void DeviceCheckTimer_Tick(object sender, EventArgs e)
        {
            string[] currentPorts = SerialPort.GetPortNames();

            // 检查是否有新设备接入
            var newPorts = currentPorts.Except(lastKnownPorts).ToArray();
            if (newPorts.Length > 0)
            {
                foreach (var port in newPorts)
                {
                    // 更新下拉框
                    portComboBox.Items.Add(port);
                    ShowBalloonTip($"检测到新设备接入: {port}");
                }
            }

            // 检查是否有设备断开
            var removedPorts = lastKnownPorts.Except(currentPorts).ToArray();
            if (removedPorts.Length > 0)
            {
                foreach (var port in removedPorts)
                {
                    // 从下拉框移除断开的端口
                    portComboBox.Items.Remove(port);
                    ShowBalloonTip($"检测到设备移除: {port}");

                    // 如果断开的设备是当前选中的设备，清空选中项并更新连接状态
                    if (portComboBox.SelectedItem != null && portComboBox.SelectedItem.ToString() == port)
                    {
                        portComboBox.SelectedIndex = -1; // 清空选中
                    }
                }
            }

            // 更新最后一次检测的设备列表
            lastKnownPorts = currentPorts;
        }

        private void ShowBalloonTip(string message)
        {
            notifyIcon.BalloonTipTitle = "设备状态变化";
            notifyIcon.BalloonTipText = message;
            notifyIcon.ShowBalloonTip(3000); // 气泡提示显示3秒
        }


        private void Form1_Load(object sender, EventArgs e)
        {
            string[] ports = SerialPort.GetPortNames();
            portComboBox.Items.AddRange(ports);
            if (ports.Length > 0)
            {
                portComboBox.SelectedIndex = 0;
            }

            serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
        }

        /// <summary>
        /// 连接串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void connectButton_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                try
                {
                    serialPort1.Close();
                    connectButton.Text = "连接";
                    ApiLog.Debug("断开连接");
                    ConnectionStatusLabel.Visible = true;
                    ConnectionStatusLabel.Text = "断开连接";
                    ConnectionStatusLabel.ForeColor = Color.Red;
                }
                catch (Exception ex)
                {
                    ApiLog.Debug("断开连接失败: " + ex.Message);
                    MessageBox.Show("断开连接失败: " + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                if (string.IsNullOrEmpty(portComboBox.Text))
                {
                    ApiLog.Debug("串口不能为空，请先连接设备");
                    MessageBox.Show("串口不能为空，请先连接设备", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                serialPort1.PortName = portComboBox.Text;
                serialPort1.BaudRate = 115200;
                serialPort1.DataBits = 8;
                serialPort1.StopBits = StopBits.One;
                serialPort1.Parity = Parity.None;

                try
                {
                    serialPort1.Open();
                    connectButton.Text = "断开连接";
                    ApiLog.Debug("连接成功");
                    ConnectionStatusLabel.Visible = true;
                    ConnectionStatusLabel.Text = "连接成功";
                    ConnectionStatusLabel.ForeColor = Color.Green;
                }
                catch (Exception ex)
                {
                    ApiLog.Debug("连接失败: " + ex.Message);
                    MessageBox.Show("连接串口失败: " + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }


        /// <summary>
        /// 设置Code
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void setcodebutton_Click(object sender, EventArgs e)
        {
            // 检查串口是否已连接
            if (!serialPort1.IsOpen)
            {
                // 处理断开连接逻辑
                serialPort1.Close();
                connectButton.Text = "连接";
                ApiLog.Debug("断开连接");
                ConnectionStatusLabel.Visible = true;
                ConnectionStatusLabel.Text = "断开连接";
                ConnectionStatusLabel.ForeColor = Color.Red;
                MessageBox.Show("请先连接串口", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // 显示弹出页
            SetCode setcode = new SetCode();
            if (setcode.ShowDialog() == DialogResult.OK)
            {
                // 检查并设置各个文本框的值
                bool hasCode = !string.IsNullOrWhiteSpace(setcode.Code);
                bool hasBatch = !string.IsNullOrWhiteSpace(setcode.Batch);
                bool hasFirmware = !string.IsNullOrWhiteSpace(setcode.Firmware);

                if (hasCode && hasBatch && hasFirmware)
                {
                    // 将值设置到相应的文本框
                    codeTextBox.Text = setcode.Code;
                    batchtextBox.Text = setcode.Batch;
                    firmtextBox.Text = setcode.Firmware;

                    codeUp = setcode.Code;
                    batchUp = setcode.Batch;
                    firmwareUp = setcode.Firmware;
                    // 将光标移动到 dmTextBox
                    //dmTextBox.Focus();
                    dmTextBox1.Focus();
                }
                else
                {
                    MessageBox.Show("请确保所有字段都已填写完整", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        /// <summary>
        /// 开始测试
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void startTestButton_Click(object sender, EventArgs e)
        {
            // 清空进度条
            progressBar.Value = progressBar.Minimum;
            SetProgressBarColor(progressBar, PBST_NORMAL);  // 重置进度条颜色


            //清除测试结果
            statusLabel.Text = "";
            statusLabel.Visible = false;  // 隐藏状态标签

            lblBluetoothTest.ForeColor = Color.Black;
            lblBatteryTest.ForeColor = Color.Black;
            lblPCBTest.ForeColor = Color.Black;
            lblAnalogTest.ForeColor = Color.Black;
            lblWorkTest.ForeColor = Color.Black;

            // 检查串口是否已连接
            if (!serialPort1.IsOpen)
            {
                // 处理断开连接逻辑
                serialPort1.Close();
                connectButton.Text = "连接";
                ApiLog.Debug("断开连接");
                ConnectionStatusLabel.Visible = true;
                ConnectionStatusLabel.Text = "断开连接";
                ConnectionStatusLabel.ForeColor = Color.Red;
                MessageBox.Show("请先连接串口", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            // 参数校验
            if ((string.IsNullOrEmpty(codeTextBox.Text) || codeTextBox.Text == "code") ||
               (string.IsNullOrEmpty(batchtextBox.Text) || batchtextBox.Text == "批号") ||
               (string.IsNullOrEmpty(firmtextBox.Text) || firmtextBox.Text == "固件版本号")
               )
            {
                MessageBox.Show("请先设置Code", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (!string.IsNullOrEmpty(dmTextBox1.Text))
            {
                string pattern = "^[0-9A-Z]{7}$";
                if (Regex.IsMatch(dmTextBox1.Text, pattern))
                {
                    #region 下盖码合法性校验API
                    var client = new HttpClientHelper(ConfigurationManager.AppSettings["ServerUrl"]);

                    // 示例：发送JSON请求
                    var jsonRequest = new
                    {
                        cover_code = dmTextBox1.Text,
                        sc = "30b9c3ca5e9911ef9aa806433e9aa661",
                        sv = "09b9c3ca5e9711ef9a806433e4aa66b6"
                    };

                    try
                    {
                        string jsonResponse = await client.PostJsonAsync("/api/FindCoverCode", jsonRequest);

                        var response = JsonConvert.DeserializeObject<ApiResponse>(jsonResponse);
                        if (response.Code == 200)
                        {
                            startTestButton.Enabled = false;
                            startTest();
                            statusLabel.Visible = true;
                            statusLabel.ForeColor = Color.Green; // 设置文字颜色为绿色
                            statusLabel.Text = "测试中...";
                        }
                        else
                        {
                            UpdateProgressBar(false, response.Message);
                        }
                    }
                    catch
                    {
                        UpdateProgressBar(false, "服务器内部错误");
                    }
                    #endregion
                }
                else
                {
                    MessageBox.Show("dm码格式校验失败", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            else
            {
                MessageBox.Show("请先读取dm码", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        #region 参数校验
        private void parseData1(byte[] buffer)
        {
            #region 数据校验
            byte dataLength = buffer[1];
            byte statusID = buffer[2];
            byte sequenceIDReceived = buffer[3];
            byte productType = buffer[4];

            byte[] result = new byte[buffer.Length - 6];
            Array.Copy(buffer, 5, result, 0, result.Length);

            byte checksum = CalculateChecksum(statusID, sequenceIDReceived, productType, result);
            byte checksumReceived = buffer[buffer.Length - 1];

            if (!ValidateDataLength(buffer, dataLength) ||
                !ValidateSequenceID(sequenceIDReceived) ||
                !ValidateProductType(productType) ||
                !ValidateChecksum(checksum, checksumReceived))
            {
                return;
            }
            #endregion

            string strBuffer = BitConverter.ToString(buffer);
            ProcessResponse(buffer, statusID, strBuffer);
        }

        private byte CalculateChecksum(byte statusID, byte sequenceIDReceived, byte productType, byte[] result)
        {
            return (byte)(statusID + sequenceIDReceived + productType + result.Sum(b => b));
        }

        private bool ValidateDataLength(byte[] buffer, byte dataLength)
        {
            if (buffer.Length != (int)dataLength + 3)
            {
                string megs = "下位机返回数据长度校验失败";


                ApiLog.Debug(megs);
                LogAndStopTest(megs);
                //stopTest();
                //UpdateProgressBar(false, megs);
                return false;
            }
            return true;
        }

        private bool ValidateSequenceID(byte sequenceIDReceived)
        {
            if (sequenceIDReceived != sequenceID)
            {
                string megs = "收到消息验证顺序ID失败";
                ApiLog.Debug(megs);
                LogAndStopTest(megs);
                //stopTest();
                //UpdateProgressBar(false, megs);
                return false;
            }
            return true;
        }

        private bool ValidateProductType(byte productType)
        {
            if (productType != ProductType)
            {
                string megs = "下位机返回数据验证产品类型失败";
                ApiLog.Debug(megs);
                LogAndStopTest(megs);
                //stopTest();
                //UpdateProgressBar(false, megs);
                return false;
            }
            return true;
        }

        private bool ValidateChecksum(byte checksum, byte checksumReceived)
        {
            if (checksum != checksumReceived)
            {
                string megs = "下位机返回数据验证校验和失败";
                ApiLog.Debug(megs);
                LogAndStopTest(megs);
                //stopTest();
                //UpdateProgressBar(false, megs);
                return false;
            }
            return true;
        }

        private void ProcessResponse(byte[] buffer, byte statusID, string strBuffer)
        {
            //主动上传
            if (statusID == StatusIDReply)
            {
                HandleStatusReply(buffer, strBuffer);
            }
            //回复确认
            else if (statusID == StatusIDConfirm)
            {
                HandleStatusConfirm(buffer, strBuffer);
            }
            else
            {
                ApiLog.Debug($"未知状态ID: {statusID}");
            }
        }
        #region 主动上传解析
        private void HandleStatusReply(byte[] buffer, string strBuffer)
        {
            switch (buffer[5])
            {
                case CommandBluetoothTestResultUpload:
                    HandleBluetoothTestResult(buffer, strBuffer);
                    break;
                case CommandCodeResultUpload:
                    HandleCodeResult(buffer, strBuffer);
                    break;
            }
        }

        private void HandleBluetoothTestResult(byte[] buffer, string strBuffer)
        {
            startTestRes = true;  // 收到测试结果
            string megs = "接收到下位机蓝牙测试结果上传：" + strBuffer;
            ApiLog.Debug(megs);
            replyConfirm(CommandBluetoothTestResultUpload, "蓝牙测试确认");

            switch (buffer[6])
            {
                case 0x00:
                    ProcessBluetoothTestSuccess(buffer);
                    break;
                case 0x05:
                    LogAndStopTest("蓝牙连接测试失败，蓝牙数据通信测试失败");
                    break;
                case 0x06:
                    LogAndStopTest("蓝牙连接测试成功，蓝牙数据通信测试失败");
                    break;
                case 0x09:
                    LogAndStopTest("固件版本不一致");
                    break;
                default:
                    LogAndStopTest("蓝牙测试未知错误");
                    break;
            }
        }

        private void ProcessBluetoothTestSuccess(byte[] buffer)
        {
            string megs = "蓝牙状态结果：蓝牙测试成功";
            ApiLog.Debug(megs);

            byte[] macBytes = new byte[6];
            Array.Copy(buffer, 7, macBytes, 0, 6);
            macDown = string.Concat(macBytes.Select(b => b.ToString("X2")));

            byte[] firmwareBytes = new byte[3];
            Array.Copy(buffer, 16, firmwareBytes, 0, 3);
            firmwareDown = string.Concat(Array.ConvertAll(firmwareBytes, b => b.ToString()));

            // 设置Code
            setCode();
        }

        private void HandleCodeResult(byte[] buffer, string strBuffer)
        {
            setCodeRes = true; // 收到主动上报的设置Code结果
            string megs = "接收到下位设置CODE结果上传:" + strBuffer;
            ApiLog.Debug(megs);
            replyConfirm(CommandCodeResultUpload, "设置CODE确认");

            switch (buffer[6])
            {
                case 0x00:
                    HandleeCodeSuccessfulCodeSetting();
                    break;
                case 0x02:
                    LogAndStopTest("发射器返回CODE的CRC16值不一致");
                    break;
                case 0x06:
                    LogAndStopTest("无法与发射器连接通信，导致设置失败");
                    break;
                case 0x07:
                    LogAndStopTest("发射器返回异常，导致设置失败");
                    break;
                case 0x0B:
                    HandleProductionProcessFlags(buffer);
                    break;
                default:
                    LogAndStopTest("设置CODE结果上传未知错误");
                    break;
            }
        }

        private async void HandleeCodeSuccessfulCodeSetting()
        {
            string successMessage = "设置Code结果：成功";
            ApiLog.Debug(successMessage);

            #region
            //// 获取代码
            //BluetoothTestSensorCodes acode = BluetoothTestSensorCodesDao.GetCode(codeUp, batchUp, firmwareDown);
            //if (string.IsNullOrEmpty(acode.code))
            //{
            //    LogAndStopTest("Code不存在");
            //    return;
            //}

            //// 检查下盖码是否存在
            //SensorCoverInfo coverInfo = SensorCoverInfoDao.GetCoverInfo(dmTextBox1.Text);
            //if (string.IsNullOrEmpty(coverInfo.cover_code))
            //{
            //    LogAndStopTest("下盖DM码不存在");
            //    return;
            //}

            //BluetoothTestSensorInfo dmCode = BluetoothTestSensorInfoDao.GetCoverCode(dmTextBox1.Text);

            //if (!string.IsNullOrEmpty(dmCode.cover_code))
            //{
            //    LogAndStopTest("下盖DM码已被使用");
            //    return;
            //}
            //// Get the switch value from config
            //bool isMacCheckEnabled = Convert.ToBoolean(ConfigurationManager.AppSettings["EnableMacCheck"]);
            //if (isMacCheckEnabled)
            //{
            //    BluetoothTestSensorInfo mac = BluetoothTestSensorInfoDao.GetMac(macDown);
            //    // 如果 mac_address 存在，则直接返回
            //    if (!string.IsNullOrEmpty(mac.mac_address))
            //    {
            //        LogAndStopTest("该传感器已存在");
            //        return;
            //    }
            //}

            //// 记录到数据库
            //try
            //{
            //    BluetoothTestSensorInfo newTestRes = new BluetoothTestSensorInfo
            //    {
            //        cover_code = dmTextBox1.Text,
            //        code_id = acode.id,
            //        mac_address = macDown,
            //    };

            //    BluetoothTestSensorInfoDao.Insert(newTestRes);
            //    // 最终结束测试和更新进度条
            //    stopTest();
            //    UpdateProgressBar(true, successMessage);
            //}
            //catch (Exception ex)
            //{
            //    string message = "记录测试结果失败: " + ex.Message;
            //    ApiLog.Error(message);
            //    LogAndStopTest(message);
            //    return;
            //}

            #endregion

            var client = new HttpClientHelper(ConfigurationManager.AppSettings["ServerUrl"]);

            // 示例：发送JSON请求
            var jsonRequest = new
            {
                mac_address = macDown,
                cover_code = dmTextBox1.Text,
                code = codeUp,
                batch = batchUp,
                firmware = firmwareDown,
                sc = "30b9c3ca5e9911ef9aa806433e9aa661",
                sv = "60b9c3ca5e9711ef9a806433e4aa661h"
            };

            try
            {
                string jsonResponse = await client.PostJsonAsync("/api/UploadTest", jsonRequest);

                var response = JsonConvert.DeserializeObject<ApiResponse>(jsonResponse);
                if (response.Code == 200)
                {
                    // 最终结束测试和更新进度条
                    stopTest();
                    UpdateProgressBar(true, successMessage);
                }
                else
                {
                    LogAndStopTest(response.Message);
                }

                // 处理 jsonResponse 的逻辑
            }
            catch
            {
                LogAndStopTest("服务器内部错误");
            }
        }


        private void HandleProductionProcessFlags(byte[] buffer)
        {
            // 解析发射器生产工序检测位 (2~5字节), 只处理最后1字节 (bit0~bit7)
            byte productionProcessFlags = buffer[10]; // 获取第4字节的工序检测位

            // 根据bit结果设置控件颜色
            //SetProcessResult(productionProcessFlags, 7, lblBluetoothTest);  // 蓝牙整机工装检测
            //SetProcessResult(productionProcessFlags, 6, lblBatteryTest);    // 电池电压检测
            //SetProcessResult(productionProcessFlags, 5, lblPCBTest);        // PCBA检测
            //SetProcessResult(productionProcessFlags, 4, lblLightTest);      // 遮光检测
            //SetProcessResult(productionProcessFlags, 3, lblAnalogTest);     // 模拟前端芯片电性能检测
            //SetProcessResult(productionProcessFlags, 2, lblPowerOffTest);   // 功耗测试-关断态检测
            //SetProcessResult(productionProcessFlags, 1, lblStandbyTest);    // 功耗测试-待机态检测
            //SetProcessResult(productionProcessFlags, 0, lblWorkTest);       // 功耗测试-工作态检测

            // 根据bit结果设置控件颜色
            SetProcessResult(productionProcessFlags, 4, lblBluetoothTest);      // bit4：蓝牙整机工装检测位；
            SetProcessResult(productionProcessFlags, 3, lblBatteryTest);     // bit3：电池电压检测位；
            SetProcessResult(productionProcessFlags, 2, lblPCBTest);   // bit2：PCBA检测位；
            SetProcessResult(productionProcessFlags, 1, lblAnalogTest);    // bit1：模拟前端芯片电性能检测位；
            SetProcessResult(productionProcessFlags, 0, lblWorkTest);       // bit0：功耗测试-工作态检测位。


            // 解析工厂模式停留时间 (6~9字节)
            int factoryModeTimeInSeconds = (buffer[11] << 24) + (buffer[12] << 16) + (buffer[13] << 8) + buffer[14]; // 取出秒数


            if (factoryModeTimeInSeconds <= 3600)
            {
                // 秒数小于等于3600，直接显示秒
                lblFactoryModeTime.Text = $"{factoryModeTimeInSeconds} 秒";
            }
            else
            {
                // 秒数大于3600，转换为小时并保留小数点后两位
                double factoryModeTimeInHours = factoryModeTimeInSeconds / 3600.0;
                lblFactoryModeTime.Text = $"{factoryModeTimeInHours:F2} 小时";
            }


            // 记录日志或通知用户检测位不全
            LogAndStopTest("测试失败");
        }

        private void SetProcessResult(byte flags, int bitPosition, Label label)
        {
            // 根据bit位置判断是通过还是未通过
            if ((flags & (1 << bitPosition)) != 0)
            {
                // 检测通过，设置为绿色
                label.ForeColor = Color.Green;
            }
            else
            {
                // 检测未通过，设置为红色
                label.ForeColor = Color.Red;
            }
        }
        #endregion

        #region 回复确认
        private void HandleStatusConfirm(byte[] buffer, string strBuffer)
        {
            switch (buffer[5])
            {
                case CommandStartBluetoothTest:
                    HandleStartBluetoothTestConfirm(buffer, strBuffer);
                    break;
                case CommandSetCode:
                    HandleSetCodeConfirm(buffer, strBuffer);
                    break;
                case CommandStopBluetoothTest:
                    HandleStopBluetoothTestConfirm(buffer, strBuffer);
                    break;
                default:
                    ApiLog.Debug($"未知指令:{buffer[6]}");
                    break;
            }
        }

        private void HandleStartBluetoothTestConfirm(byte[] buffer, string strBuffer)
        {
            startTestStatus = true; // 收到下位机返回开始蓝牙测试状态
            string megs = "接收到下位机蓝牙状态回复：" + strBuffer;
            ApiLog.Debug(megs);

            switch (buffer[6])
            {
                case 0x00:
                    ApiLog.Debug("蓝牙状态：开始蓝牙测试");
                    break;
                case 0x03:
                    ApiLog.Debug("蓝牙状态：下位机正在进行设置CODE,继续等待...");
                    break;
                case 0x04:
                    ApiLog.Debug("蓝牙状态：下位机正在进行蓝牙测试,继续等待...");
                    break;
                case 0x08:
                    LogAndStopTest("蓝牙状态：上一次蓝牙测试未执行结束测试指令");
                    break;
                default:
                    LogAndStopTest("蓝牙状态：开始蓝牙测试未知错误" + buffer[6]);
                    break;
            }
        }

        private void HandleSetCodeConfirm(byte[] buffer, string strBuffer)
        {
            setCodeStatus = true; // 收到下位机返回设置Code回复
            string megs = "接收到下位机设置Code回复：" + strBuffer;
            ApiLog.Debug(megs);

            switch (buffer[6])
            {
                case 0x00:
                    ApiLog.Debug("设置CODE：设置CODE成功");
                    break;
                case 0x02:
                    LogAndStopTest("设置CODE：设置CODE的CRC16值不相同");
                    break;
                case 0x03:
                    ApiLog.Debug("设置CODE：下位机正在进行设置CODE,继续等待...");
                    break;
                case 0x04:
                    ApiLog.Debug("设置CODE：下位机正在进行蓝牙测试,继续等待...");
                    break;
                case 0x05:
                    LogAndStopTest("设置CODE：未运行蓝牙测试（未建立蓝牙连接），导致设置失败");
                    break;
                default:
                    LogAndStopTest("设置CODE：设置CODE确认未知错误" + buffer[6]);
                    break;
            }
        }

        private void HandleStopBluetoothTestConfirm(byte[] buffer, string strBuffer)
        {
            string megs = "接收到下位机停止蓝牙测试确认：" + strBuffer;
            ApiLog.Debug(megs);
            switch (buffer[6])
            {
                case 0x00:
                    ApiLog.Debug("结束蓝牙测试成功");
                    break;
                case 0x0A:
                    ApiLog.Debug("下位机此时不能停止，稍后再试");
                    break;
                default:
                    LogAndStopTest("结束蓝牙测试下位机返回未知错误" + buffer[6]);
                    break;
            }
        }

        #endregion

        private void LogAndStopTest(string message)
        {
            ApiLog.Debug(message);
            stopTest();
            UpdateProgressBar(false, message);
        }


        #endregion

        #region 发送数据
        /// <summary>
        /// 发送指令
        /// </summary>
        /// <param name="command">byte[]</param>
        private void sendCommand(byte[] command, string commandname)
        {
            if (serialPort1.IsOpen)
            {
                try
                {
                    string strComm = BitConverter.ToString(command);
                    serialPort1.Write(command, 0, command.Length);
                    ApiLog.Debug("上位机发送" + commandname + "指令: " + strComm);
                }
                catch (Exception ex)
                {
                    ApiLog.Debug("上位机发送" + commandname + "指令: " + ex.Message);
                }
            }
            else
            {
                ApiLog.Debug("串口未打开，无法发送指令");
            }
        }

        #endregion

        #region 进度条      
        private async void UpdateProgressBar(bool isSuccess, string megs)
        {
            progressBar.Minimum = 0;
            progressBar.Maximum = 100;
            progressBar.Value = 0;

            // 设置进度条颜色并从 0 到 100 运行
            for (int i = 0; i <= 100; i++)
            {
                progressBar.Value = i;
                SetProgressBarColor(progressBar, isSuccess ? PBST_NORMAL : PBST_ERROR);
                //System.Threading.Thread.Sleep(10); // 模拟延迟

                await Task.Delay(10); // 使用异步延迟
            }

            // 更新状态标签
            statusLabel.Visible = true;
            if (isSuccess)
            {
                statusLabel.ForeColor = Color.Green; // 设置文字颜色为绿色
                statusLabel.Text = "测试成功！请扫描下一个设备";
            }
            else
            {
                statusLabel.ForeColor = Color.Red; // 设置文字颜色为红色
                statusLabel.Text = megs;
            }

            // 清空 dmTextBox1 并重新设置焦点
            dmTextBox1.Text = "";
            dmTextBox1.Focus();

            // 重新启用开始按钮
            startTestButton.Enabled = true;
        }


        private void SetProgressBarColor(ProgressBar progressBar, int state)
        {
            SendMessage(progressBar.Handle, PBM_SETSTATE, (IntPtr)state, IntPtr.Zero);
        }
        #endregion

        #region 构建数据包
        /// <summary>
        /// 构建数据包
        /// </summary>
        /// <param name="commandHeader"></param>
        /// <param name="statusID"></param>
        /// <param name="sequenceID"></param>
        /// <param name="product"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private static byte[] buildPacket(byte commandHeader, byte statusID, byte sequenceID, byte product, byte[] data)
        {
            // 计算数据包长度
            int length = data.Length + 3;
            //整包校验和
            byte checksum = (byte)(statusID + sequenceID + product + data.Sum(b => b));

            List<byte> buf = new List<byte>();
            buf.Add(commandHeader);
            buf.Add((byte)length);
            buf.Add(statusID);
            buf.Add(sequenceID);
            buf.Add(product);
            // 添加 Data 字段
            buf.AddRange(data);
            // 添加 Checksum 字段
            buf.Add(checksum);

            return buf.ToArray();
        }
        #endregion

        #region 接收数据

        private Queue<byte> receivedDataBuffer = new Queue<byte>();
        private const int MinDataLength = 8; // 期望的数据最小长度
        /// <summary>
        /// serialPort1_DataReceived
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                byte[] buffer = new byte[serialPort1.BytesToRead];
                serialPort1.Read(buffer, 0, buffer.Length);
                lock (receivedDataBuffer)
                {
                    foreach (var b in buffer)
                    {
                        receivedDataBuffer.Enqueue(b);
                    }
                }
                ProcessReceivedData();
            }
            catch (Exception ex)
            {
                ApiLog.Debug("数据接收处理异常: " + ex.Message);
            }
        }
        /// <summary>
        /// ProcessReceivedData
        /// </summary>
        private void ProcessReceivedData()
        {
            // 使用 Invoke 确保操作在 UI 线程中进行
            this.Invoke(new Action(() =>
            {
                lock (receivedDataBuffer)
                {
                    while (receivedDataBuffer.Count >= MinDataLength)
                    {
                        // 检查包头是否为 0xA0
                        if (receivedDataBuffer.Peek() != HeaderCommandDown)
                        {
                            // 如果包头不正确，移除无效字节
                            receivedDataBuffer.Dequeue();
                            continue;
                        }

                        // 至少需要两个字节来读取长度信息
                        if (receivedDataBuffer.Count < 2)
                        {
                            break; // 不够长度，等待更多数据
                        }

                        // 读取数据长度字节（第二个字节）
                        byte[] headerBytes = receivedDataBuffer.ToArray();
                        int dataLength = headerBytes[1];
                        int totalPacketLength = dataLength + 3; // 头+长度字节+校验字节

                        // 检查是否收到了完整的数据包
                        if (receivedDataBuffer.Count < totalPacketLength)
                        {
                            // 数据长度不够，等待更多数据
                            break;
                        }

                        // 从队列中提取完整的数据包
                        byte[] packet = new byte[totalPacketLength];
                        for (int i = 0; i < totalPacketLength; i++)
                        {
                            packet[i] = receivedDataBuffer.Dequeue();
                        }

                        // 解析数据
                        try
                        {
                            parseData1(packet);

                            // 判断是否收到了期望的两个回复
                            if (startTestStatus && startTestRes)
                            {
                                CancelTimeout(cts);
                                startTestStatus = false;
                                startTestRes = false;
                            }

                            if (setCodeStatus && setCodeRes)
                            {
                                CancelTimeout(cts1);
                                setCodeStatus = false;
                                setCodeRes = false;
                            }
                        }
                        catch (Exception ex)
                        {
                            ApiLog.Debug("数据处理异常: " + ex.Message);
                        }
                    }
                }
            }));
        }

        //取消超时任务
        private void CancelTimeout(CancellationTokenSource cts)
        {
            if (cts != null && !cts.IsCancellationRequested)
            {
                cts.Cancel();
            }
        }

        #endregion

        #region 开始测试指令
        ///// <summary>
        ///// 开启蓝牙测试
        ///// </summary>
        private void startTest()
        {
            stemp = "startTest";
            // 将 firmText 转换为字节数组
            string firm = firmtextBox.Text;
            byte[] firmBytes = firm.Select(c => byte.Parse(c.ToString())).ToArray();
            List<byte> buf = new List<byte>();
            buf.Add(CommandStartBluetoothTest);
            buf.AddRange(firmBytes);
            byte[] command = buf.ToArray();// 开始蓝牙测试指令

            byte[] Acommand = buildPacket(HeaderCommandUp, StatusIDReply, sequenceID, ProductType, command);
            sendCommand(Acommand, "开始蓝牙测试");

            cts = new CancellationTokenSource(); // 初始化
            timeoutTask = Task.Delay(TimeoutDuration, cts.Token).ContinueWith(t =>
            {
                if (!t.IsCanceled)
                {
                    this.Invoke(new Action(() =>
                    {
                        ApiLog.Debug("蓝牙测试超时");
                        stopTest();  //结束测试
                    }));
                }
            }, TaskScheduler.FromCurrentSynchronizationContext());

            // 更新顺序ID
            sequenceID++;
            if (sequenceID > 0xFF)
            {
                sequenceID = 0x00; // 循环顺序ID
            }
        }
        #endregion

        #region 设置Code指令
        /// <summary>
        /// 设置Code
        /// </summary>
        private void setCode()
        {
            stemp = "setCode";

            string codeStr = codeTextBox.Text;
            byte[] codeBytes = codeStr.Split(' ').Select(hex => Convert.ToByte(hex, 16)).ToArray();
            byte[] command = { CommandSetCode };  // 设置CODE
            List<byte> data = new List<byte>();
            data.Add(CommandSetCode);
            data.AddRange(codeBytes);

            byte[] Acommand = buildPacket(HeaderCommandUp, StatusIDReply, sequenceID, ProductType, data.ToArray());
            sendCommand(Acommand, "设置CODE");

            cts1 = new CancellationTokenSource(); // 初始化
            timeoutTask = Task.Delay(TimeoutDuration, cts1.Token).ContinueWith(t =>
            {
                if (!t.IsCanceled)
                {
                    this.Invoke(new Action(() =>
                    {
                        ApiLog.Debug("设置Code超时");
                        stopTest();  //结束测试
                    }));
                }
            }, TaskScheduler.FromCurrentSynchronizationContext());

            // 更新顺序ID
            sequenceID++;
            if (sequenceID > 0xFF)
            {
                sequenceID = 0x00; // 循环顺序ID
            }
        }

        //private void startTest()
        //{
        //    stemp = "startTest";
        //    string firm = firmtextBox.Text;
        //    byte[] firmBytes = firm.Select(c => byte.Parse(c.ToString())).ToArray();
        //    List<byte> buf = new List<byte> { CommandStartBluetoothTest };
        //    buf.AddRange(firmBytes);

        //    byte[] command = buf.ToArray();
        //    byte[] Acommand = buildPacket(HeaderCommandUp, StatusIDReply, sequenceID, ProductType, command);
        //    sendCommand(Acommand, "开始蓝牙测试");

        //    StartTimeoutTask(cts, () =>
        //    {
        //        ApiLog.Debug("蓝牙测试超时");
        //        stopTest();
        //    });

        //    sequenceID++;
        //    if (sequenceID > 0xFF)
        //    {
        //        sequenceID = 0x00; // 循环顺序ID
        //    }
        //}

        //private void setCode()
        //{
        //    stemp = "setCode";
        //    string codeStr = codeTextBox.Text;
        //    byte[] codeBytes = codeStr.Split(' ').Select(hex => Convert.ToByte(hex, 16)).ToArray();
        //    List<byte> data = new List<byte> { CommandSetCode };
        //    data.AddRange(codeBytes);

        //    byte[] Acommand = buildPacket(HeaderCommandUp, StatusIDReply, sequenceID, ProductType, data.ToArray());
        //    sendCommand(Acommand, "设置CODE");

        //    StartTimeoutTask(cts1, () =>
        //    {
        //        ApiLog.Debug("设置Code超时");
        //        stopTest();
        //    });

        //    sequenceID++;
        //    if (sequenceID > 0xFF)
        //    {
        //        sequenceID = 0x00; // 循环顺序ID
        //    }
        //}

        #endregion

        #region 回复确认指令
        /// <summary>
        /// 回复确认
        /// </summary>
        /// <param name="command"></param>
        private void replyConfirm(byte command, string commandname)
        {
            stemp = "replyConfirm";

            byte[] data = { command };

            byte[] Acommand = buildPacket(HeaderCommandUp, StatusIDConfirm, sequenceID, ProductType, data);
            sendCommand(Acommand, commandname);

            // 更新顺序ID
            sequenceID++;
            if (sequenceID > 0xFF)
            {
                sequenceID = 0x00; // 循环顺序ID
            }
        }
        #endregion

        #region 终止蓝牙测试指令
        /// <summary>
        /// 终止蓝牙测试
        /// </summary>
        private void stopTest()
        {

            startTestStatus = true;
            startTestRes = true;
            setCodeStatus = true;
            setCodeRes = true;

            stemp = "stopTest";

            byte[] data = { CommandStopBluetoothTest }; // 结束蓝牙测试指令

            byte[] Acommand = buildPacket(HeaderCommandUp, StatusIDReply, sequenceID, ProductType, data);
            sendCommand(Acommand, "结束蓝牙测试");
            // 更新顺序ID
            sequenceID++;
            if (sequenceID > 0xFF)
            {
                sequenceID = 0x00; // 循环顺序ID
            }
        }
        #endregion
    }
}
